﻿using System.Collections.Generic;
using Unity.Mathematics;
using UnityEngine;
using WorldMapBase.Collision;
using WorldMapBase.Display;
using WorldMapBase.Layer;
using Yoozoo.Managers;

namespace WorldMapBase.Tile
{
    public class LODTileLayerListener : ITileLayerListener, LODTileLayer.ILODScaleListener
    {
        /// <summary>
        /// 层级
        /// </summary>
        protected int m_LayerID;

        protected Dictionary<int, Dictionary<int, MultiElementTile>> renderInfoDic = new Dictionary<int, Dictionary<int, MultiElementTile>>();// <lod,<tileIdx,地图块实例类>>
        private Dictionary<int, Dictionary<int, bool>> mapPointState = new Dictionary<int, Dictionary<int, bool>>();//出生点状态 <tileIdx,<posIdx,state>> 常驻数据 靠服务器数据更新
        private IDisplayCommandInterface m_DisplayCommandInterface;

        public LODTileLayerListener(int layerID, IDisplayCommandInterface displayCommandInterface)
        {
            m_LayerID = layerID;
            m_DisplayCommandInterface = displayCommandInterface;
            renderInfoDic[0] = new Dictionary<int, MultiElementTile>(40);
            renderInfoDic[1] = new Dictionary<int, MultiElementTile>(40);
            renderInfoDic[2] = new Dictionary<int, MultiElementTile>(60);
            renderInfoDic[3] = new Dictionary<int, MultiElementTile>(100);
            renderInfoDic[4] = new Dictionary<int, MultiElementTile>(200);
        }

        /// <summary>
        /// 当添加地块时响应
        /// </summary>
        /// <param name="lodIndex">LOD等级（等价于TileLayer构造时传入的那个layerID）</param>
        /// <param name="tileIndex">地块序号</param>
        /// <param name="worldPos">地块世界坐标（地块中心的坐标）</param>
        public void OnAddTile(int lodIndex, int tileIndex, int2 worldPos)
        {
            Dictionary<int, MultiElementTile> dic;
            if (!renderInfoDic.TryGetValue(lodIndex, out dic))
            {
                dic = new Dictionary<int, MultiElementTile>();
                renderInfoDic.Add(lodIndex, dic);
            }
            //Debug.LogError(string.Format("[沙盘基础] 添加层级{0}，LOD等级{1}，地块序号为{2}的地块", m_LayerID, lodIndex, tileIndex));
            int tileSize = WorldEntry.m_iTileSize;
            WorldMapNew.MapChunckLayer tileData = null;
            tileData = WorldMapConfigData.GetTileData(m_LayerID, lodIndex, tileIndex, out tileSize, out int layerIdx, out int chunckId);
            if (tileData != null)
            {
                var tile = MultiElementTile.Create(lodIndex, tileData, tileSize, tileIndex, layerIdx, chunckId, m_DisplayCommandInterface);
                dic[tileIndex] = tile;
            }
            // 添加地表的时候 顺便把交通系统也添加了 TODO：之后要看看有没有更好的方法 不要和地表层级绑定
            //if (m_LayerID == WorldEntry.PLANE_LAYER_ID && lodIndex == 1)
            //{ 
            //    DynamicLayerMgr.worldEntry.AddTileTraffic(tileIndex, lodIndex);
            //}
        }

        public void OnAddMapAllCar()
        { 
            int lodIndex = 1;
            Dictionary<int, MultiElementTile> dic;
            if (renderInfoDic.TryGetValue(lodIndex, out dic))
            {
                foreach (var tileIndex in dic.Keys)
                {
                    DynamicLayerMgr.worldEntry.AddTileTraffic(tileIndex, lodIndex);
                }
            }
        }

        public void OnAddMapAllPoint()
        {
            Dictionary<int, MultiElementTile> dic;
            if (renderInfoDic.TryGetValue(1, out dic))
            {
                foreach (var elementTile in dic.Values)
                {
                    elementTile.CreateTileElementPool();
                }
            }
        }

        public bool IsMapPointRender()
        {
            bool render = false;
            foreach (var dic in renderInfoDic.Values)
            {
                foreach (var elementTile in dic.Values)
                {
                    render = elementTile.IsMapPointRender();
                    if (render) return render;
                }
            }
            return render;
        }

        public void OnRemoveMapAllPoint()
        {
            foreach (var dic in renderInfoDic.Values)
            {
                foreach (var elementTile in dic.Values)
                {
                    elementTile.DestroyTileElementPool();
                }
            }
        }

        public void SetMapPointState(int tileIdx, int posIdx, bool state)
        {
            // 1、保存状态
            Dictionary<int, bool> dic;
            if (!mapPointState.TryGetValue(tileIdx, out dic))
            {
                if (state)
                {
                    return;// 如果是设置一个出生点状态显示 但是当前没有显示该块 可以不设置
                }
                dic = new Dictionary<int, bool>();
                mapPointState[tileIdx] = dic;
            }
            dic[posIdx] = state;
            // 2、添加删除对象
            if (WorldEntry.bMapPointShow)
            {
                Dictionary<int, MultiElementTile> dicTile;
                if (renderInfoDic.TryGetValue(1, out dicTile))
                {
                    MultiElementTile tile;
                    if (dicTile.TryGetValue(tileIdx, out tile))
                    {
                        //添加可能存在的点
                        if (state)
                        {
                            tile.CreateTilePoint(posIdx);
                        }
                        //删除可能存在的点
                        else
                        {
                            tile.DestroyTilePoint(posIdx);
                        }
                    }
                }
            }
        }

        public bool GetMapPointState(int tileIdx, int posIdx)
        {
            bool state = true;
            Dictionary<int, bool> dic;
            if (mapPointState.TryGetValue(tileIdx,out dic))
            {
                if (dic.ContainsKey(posIdx))
                {
                    state = dic[posIdx];
                }
            }
            return state;
        }

        /// <summary>
        /// LOD百分比更新时响应
        /// </summary>
        /// <param name="lodLevel">lod等级</param>
        /// <param name="percent">当前lod缩放百分比</param>
        public virtual void OnLODScaleUpdate(int lodLevel, float percent)
        {
        }

        /// <summary>
        /// 当移除地块时响应
        /// </summary>
        /// <param name="layer">地块层级（等价于TileLayer构造时传入的那个layerID）</param>
        /// <param name="tileIndex">地块序号</param>
        public void OnRemoveTile(int lodIndex, int tileIndex)
        {
            UnityEngine.Profiling.Profiler.BeginSample("LODTileLayerListener OnRemoveTile");
            // Debug.LogError(string.Format("[沙盘基础] 移除层级{0}，LOD等级{1}，地块序号为{2}的地块", m_LayerID, lodIndex, tileIndex));
            // 移除该地块对象
            Dictionary<int, MultiElementTile> dic = null;
            if (!renderInfoDic.TryGetValue(lodIndex, out dic))
            {
                dic = new Dictionary<int, MultiElementTile>();
            }


            MultiElementTile tile;
            if(dic.TryGetValue(tileIndex,out tile))
            {
                ClassManager.Free(tile);
                dic.Remove(tileIndex);
            }
            UnityEngine.Profiling.Profiler.EndSample();
            // 地表层 移除汽车
            //if (m_LayerID == WorldEntry.PLANE_LAYER_ID && lodIndex == 1)
            //{ 
            //    DynamicLayerMgr.worldEntry.RemoveTileTraffic(tileIndex, lodIndex);
            //}
        }

        void ITileLayerListener.OnRemoveTiles(int lodIndex, int[] tileIndexs)
        {
            int tileIndex;
            MultiElementTile tile;
            var dic = renderInfoDic[lodIndex];
            bool bRemovePointState = m_LayerID == WorldEntry.MAP_POINT_ID && lodIndex == 1;
            for (int i = 0; i < tileIndexs.Length; i++)
            {
                tileIndex = tileIndexs[i];
                if (dic.TryGetValue(tileIndex, out tile))
                {
                    ClassManager.Free(tile);
                    dic.Remove(tileIndex);
                }
            }
        }

        public void ResetQuality()
        {
            foreach (var item in renderInfoDic.Values)
            {
                foreach (var item2 in item.Values)
                {
                    item2.ResetQuality();
                }
            }
        }

        public void ClearMapPointState()
        {
            mapPointState.Clear();
        }
        
        public virtual void Dispose()
        {
            foreach (var pair in renderInfoDic)
            {
                var dictionary = pair.Value;
                foreach (var tilePair in dictionary)
                {
                    var tile = tilePair.Value;
                    MultiElementTile.Free(tile);
                }
                dictionary.Clear();
            }
        }
    }
}
